package org.eiahe.hr.interview.analyzer;

import lombok.Data;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 简化版简历解析器
 * 专注于个人信息提取，去掉复杂的NLP依赖
 */
@Service
public class SimplifiedResumeAnalyzer {

    private static final Logger logger = LoggerFactory.getLogger(SimplifiedResumeAnalyzer.class);

    // 支持的文件类型
    private static final Set<String> SUPPORTED_EXTENSIONS = Set.of("pdf", "doc", "docx", "txt");

    // 最大文件大小 (10MB)
    private static final long MAX_FILE_SIZE = 10 * 1024 * 1024;

    /**
     * 从MultipartFile分析简历
     */
    public ResumeInfo analyzeResumeFromMultipart(MultipartFile file) throws IOException {
        validateFile(file);

        String originalFilename = file.getOriginalFilename();
        String extension = getFileExtension(originalFilename).toLowerCase();

        logger.info("开始分析上传文件: {}, 大小: {} bytes", originalFilename, file.getSize());

        try {
            String content = extractTextFromInputStream(file.getInputStream(), extension);
            return analyzeResumeText(content, originalFilename);
        } catch (Exception e) {
            logger.error("分析简历文件失败: {}", originalFilename, e);
            throw new IOException("简历文件分析失败: " + e.getMessage(), e);
        }
    }

    /**
     * 验证上传文件
     */
    private void validateFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件为空");
        }

        if (file.getSize() > MAX_FILE_SIZE) {
            throw new IllegalArgumentException("文件大小超过限制，最大支持10MB");
        }

        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null) {
            throw new IllegalArgumentException("无法获取文件名");
        }

        String extension = getFileExtension(originalFilename).toLowerCase();
        if (!SUPPORTED_EXTENSIONS.contains(extension)) {
            throw new UnsupportedOperationException("不支持的文件格式: " + extension +
                "。支持的格式: " + String.join(", ", SUPPORTED_EXTENSIONS));
        }
    }

    /**
     * 从InputStream提取文本内容
     */
    private String extractTextFromInputStream(InputStream inputStream, String extension) throws IOException {
        switch (extension.toLowerCase()) {
            case "txt":
                return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
            case "doc":
                return extractTextFromDoc(inputStream);
            case "docx":
                return extractTextFromDocx(inputStream);
            case "pdf":
                return extractTextFromPdf(inputStream);
            default:
                throw new UnsupportedOperationException("不支持的文件格式: " + extension);
        }
    }

    /**
     * 从DOC文档提取文本
     */
    private String extractTextFromDoc(InputStream inputStream) throws IOException {
        try (HWPFDocument document = new HWPFDocument(inputStream);
             WordExtractor extractor = new WordExtractor(document)) {
            return extractor.getText();
        } catch (Exception e) {
            logger.error("提取DOC文档文本失败", e);
            throw new IOException("无法读取DOC文档: " + e.getMessage(), e);
        }
    }

    /**
     * 从DOCX文档提取文本 - 兼容性处理
     */
    private String extractTextFromDocx(InputStream inputStream) throws IOException {
        // 先将InputStream转换为字节数组以避免版本兼容性问题
        byte[] docxBytes;
        try {
            docxBytes = inputStream.readAllBytes();
        } catch (IOException e) {
            throw new IOException("无法读取DOCX文件数据", e);
        }

        // 使用ByteArrayInputStream重新创建输入流
        try (ByteArrayInputStream bais = new ByteArrayInputStream(docxBytes);
             XWPFDocument document = new XWPFDocument(bais);
             XWPFWordExtractor extractor = new XWPFWordExtractor(document)) {
            return extractor.getText();
        } catch (Exception e) {
            logger.error("提取DOCX文档文本失败", e);
            // 如果XWPFDocument失败，尝试使用Apache Tika作为备用方案
            return extractTextWithFallback(docxBytes);
        }
    }

    /**
     * PDF文档文本提取
     */
    private String extractTextFromPdf(InputStream inputStream) throws IOException {
        try (PDDocument document = PDDocument.load(inputStream)) {
            PDFTextStripper stripper = new PDFTextStripper();
            stripper.setSortByPosition(true); // 按页面位置排序文本（保持原文顺序）
            String text = stripper.getText(document);
            logger.debug("PDF文档提取完成，页数: {}, 文本长度: {}",
                document.getNumberOfPages(), text.length());
            return text;
        } catch (Exception e) {
            logger.error("提取PDF文档文本失败", e);
            // 捕获异常时补充版本适配提示（便于后续维护）
            throw new IOException("PDFBox 2.0.29 读取PDF文档失败: " + e.getMessage(), e);
        }
    }

    /**
     * 备用文本提取方法 - 使用简单的字符串解析
     */
    private String extractTextWithFallback(byte[] docxBytes) throws IOException {
        try {
            // 简单的DOCX解析 - 查找document.xml中的文本内容
            String content = new String(docxBytes, StandardCharsets.UTF_8);

            // 使用正则表达式提取w:t标签中的文本
            Pattern textPattern = Pattern.compile("<w:t[^>]*>([^<]*)</w:t>");
            Matcher matcher = textPattern.matcher(content);

            StringBuilder result = new StringBuilder();
            while (matcher.find()) {
                String text = matcher.group(1);
                if (!text.trim().isEmpty()) {
                    result.append(text).append(" ");
                }
            }

            String extractedText = result.toString().trim();
            if (!extractedText.isEmpty()) {
                logger.info("使用备用方法成功提取DOCX文本，长度: {}", extractedText.length());
                return extractedText;
            }

            // 如果正则表达式提取失败，尝试更简单的方法
            return extractTextWithSimpleParsing(docxBytes);

        } catch (Exception e) {
            logger.warn("备用文本提取方法失败", e);
            throw new IOException("无法使用任何方法提取DOCX文档文本", e);
        }
    }

    /**
     * 更简单的文本提取方法
     */
    private String extractTextWithSimpleParsing(byte[] docxBytes) throws IOException {
        try {
            String content = new String(docxBytes, StandardCharsets.UTF_8);

            // 查找中文文本内容
            Pattern chinesePattern = Pattern.compile("[\\u4e00-\\u9fa5]+[\\u4e00-\\u9fa5\\s\\w\\p{Punct}]*");
            Matcher matcher = chinesePattern.matcher(content);

            Set<String> extractedTexts = new LinkedHashSet<>(); // 使用Set去重，LinkedHashSet保持顺序
            while (matcher.find()) {
                String text = matcher.group().trim();
                if (text.length() > 1) { // 至少包含2个字符
                    extractedTexts.add(text);
                }
            }

            String result = String.join(" ", extractedTexts);
            if (result.length() > 10) { // 确保提取到了足够的内容
                logger.info("使用简单解析方法提取DOCX文本成功，长度: {}", result.length());
                return result;
            }

            throw new IOException("无法提取到有效的文本内容");

        } catch (Exception e) {
            throw new IOException("简单文本解析失败", e);
        }
    }

    /**
     * 分析简历文本内容
     */
    public ResumeInfo analyzeResumeText(String resumeText, String source) {
        if (resumeText == null || resumeText.trim().isEmpty()) {
            throw new IllegalArgumentException("简历文本内容为空");
        }

        logger.info("开始分析简历文本，来源: {}, 文本长度: {}", source, resumeText.length());

        ResumeInfo resumeInfo = new ResumeInfo();
        resumeInfo.setSource(source);
        resumeInfo.setOriginalText(resumeText);

        // 提取个人信息
        PersonalInfo personalInfo = extractPersonalInfo(resumeText);
        resumeInfo.setPersonalInfo(personalInfo);

        // 提取教育背景
        List<EducationInfo> educationList = extractEducationInfo(resumeText);
        resumeInfo.setEducationInfo(educationList);

        logger.info("简历分析完成: 姓名={}, 电话={}, 邮箱={}, 教育经历={}条",
            personalInfo.getName(), personalInfo.getPhone(), personalInfo.getEmail(), educationList.size());

        return resumeInfo;
    }

    /**
     * 提取个人信息
     */
    private PersonalInfo extractPersonalInfo(String text) {
        PersonalInfo info = new PersonalInfo();

        // 清理文本，统一格式
        String cleanText = text.replaceAll("\\s+", " "); // 将多个空白字符替换为单个空格

        // 提取姓名 - 支持多种格式
        info.setName(extractName(cleanText));

        // 提取电话
        info.setPhone(extractPhone(cleanText));

        // 提取邮箱
        info.setEmail(extractEmail(cleanText));

        // 提取籍贯
        info.setHometown(extractHometown(cleanText));

        // 提取出生年月
        info.setBirthDate(extractBirthDate(cleanText));

        // 提取年龄
        info.setAge(extractAge(cleanText));

        // 提取政治面貌
        info.setPoliticalStatus(extractPoliticalStatus(cleanText));

        return info;
    }

    /**
     * 提取姓名
     */
    private String extractName(String text) {
        // 多种姓名提取模式，按优先级排序
        List<Pattern> namePatterns = Arrays.asList(
            // 标准格式：姓名：xxx
            Pattern.compile("(?:姓\\s*名)[：:\\s]*([\\u4e00-\\u9fa5]{2,4})"),
            // 简化格式：姓名：xxx（支持全角冒号）
            Pattern.compile("姓名[：:\\s]*([\\u4e00-\\u9fa5]{2,4})"),
            // PDF格式：名 字：xxx
            Pattern.compile("名\\s*字[：:\\s]*([\\u4e00-\\u9fa5]{2,4})"),
            // 基本信息后的姓名格式
            Pattern.compile("基本信息[\\s\\S]*?姓名[：:\\s]*([\\u4e00-\\u9fa5]{2,4})"),
            // Personal resume格式
            Pattern.compile("Personal\\s+resume[\\s\\S]*?名\\s*字[：：\\s]*([\\u4e00-\\u9fa5]{2,4})")
        );

        for (Pattern pattern : namePatterns) {
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                String name = matcher.group(1).trim();
                if (isValidChineseName(name)) {
                    logger.debug("提取到姓名: {} (使用模式: {})", name, pattern.pattern());
                    return name;
                }
            }
        }

        logger.warn("未能提取到有效姓名");
        return null;
    }

    /**
     * 验证中文姓名有效性
     */
    private boolean isValidChineseName(String name) {
        if (name == null || name.trim().isEmpty()) {
            return false;
        }

        name = name.trim();

        // 长度检查：中文姓名通常2-4个字符
        if (name.length() < 2 || name.length() > 4) {
            return false;
        }

        // 必须全部为中文字符
        if (!name.matches("[\\u4e00-\\u9fa5]+")) {
            return false;
        }

        // 排除常见的非姓名词汇
        Set<String> excludeWords = Set.of("个人", "信息", "教育", "背景", "工作", "经历",
            "技能", "证书", "荣誉", "评价", "联系", "方式", "专业", "学历", "毕业");

        return !excludeWords.contains(name);
    }

    /**
     * 提取电话号码
     */
    private String extractPhone(String text) {
        List<Pattern> phonePatterns = Arrays.asList(
            // 联系方式：手机号
            Pattern.compile("(?:联系方式)[：:\\s]*([1][3-9]\\d{9})"),
            // 电话：手机号
            Pattern.compile("(?:电\\s*话|手\\s*机|联系电话)[：:\\s]*([1][3-9]\\d{9})"),
            // 英文格式
            Pattern.compile("(?:tel|phone)[：:\\s]*([1][3-9]\\d{9})"),
            // 直接匹配手机号（更宽泛的模式）
            Pattern.compile("([1][3-9]\\d{9})"),
            // 11位数字
            Pattern.compile("(?:电\\s*话)[：:\\s]*(\\d{11})")
        );

        for (Pattern pattern : phonePatterns) {
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                String phone = matcher.group(1).replaceAll("\\s+", "");
                if (isValidPhone(phone)) {
                    logger.debug("提取到电话: {} (使用模式: {})", phone, pattern.pattern());
                    return phone;
                }
            }
        }

        logger.warn("未能提取到有效电话号码");
        return null;
    }

    /**
     * 验证电话号码
     */
    private boolean isValidPhone(String phone) {
        return phone != null && phone.matches("1[3-9]\\d{9}");
    }

    /**
     * 提取邮箱
     */
    private String extractEmail(String text) {
        Pattern emailPattern = Pattern.compile("(?:邮\\s*箱|email)[：:\\s]*([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})");
        Matcher matcher = emailPattern.matcher(text);

        if (matcher.find()) {
            String email = matcher.group(1);
            logger.debug("提取到邮箱: {}", email);
            return email;
        }

        // 尝试直接匹配邮箱格式
        Pattern directEmailPattern = Pattern.compile("([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})");
        Matcher directMatcher = directEmailPattern.matcher(text);
        if (directMatcher.find()) {
            String email = directMatcher.group(1);
            logger.debug("直接提取到邮箱: {}", email);
            return email;
        }

        logger.warn("未能提取到邮箱");
        return null;
    }

    /**
     * 提取籍贯
     */
    private String extractHometown(String text) {
        Pattern pattern = Pattern.compile("(?:籍\\s*贯)[：:\\s]*([\\u4e00-\\u9fa5]{2,10})");
        Matcher matcher = pattern.matcher(text);

        if (matcher.find()) {
            String hometown = matcher.group(1);
            logger.debug("提取到籍贯: {}", hometown);
            return hometown;
        }

        return null;
    }

    /**
     * 提取出生年月
     */
    private String extractBirthDate(String text) {
        List<Pattern> birthPatterns = Arrays.asList(
            Pattern.compile("(?:出生年月)[：:\\s]*(\\d{4}\\.\\d{1,2})"),
            Pattern.compile("(?:出生)[：:\\s]*(\\d{4}[-/年]\\d{1,2})"),
            Pattern.compile("(?:生日)[：:\\s]*(\\d{4}\\.\\d{1,2})")
        );

        for (Pattern pattern : birthPatterns) {
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                String birthDate = matcher.group(1);
                logger.debug("提取到出生年月: {}", birthDate);
                return birthDate;
            }
        }

        return null;
    }

    /**
     * 提取年龄
     */
    private Integer extractAge(String text) {
        List<Pattern> agePatterns = Arrays.asList(
            // 年龄；25岁 (注意分号)
            Pattern.compile("(?:年\\s*龄)[；;：:\\s]*(\\d{1,2})(?:岁)?"),
            // 年龄：25岁
            Pattern.compile("(?:年\\s*龄)[：:\\s]*(\\d{1,2})(?:岁)?"),
            // age: 25
            Pattern.compile("(?:age)[：:\\s]*(\\d{1,2})")
        );

        for (Pattern pattern : agePatterns) {
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                try {
                    int age = Integer.parseInt(matcher.group(1));
                    if (age > 15 && age < 70) { // 合理的年龄范围
                        logger.debug("提取到年龄: {}", age);
                        return age;
                    }
                } catch (NumberFormatException e) {
                    logger.debug("年龄格式转换失败: {}", matcher.group(1));
                }
            }
        }

        return null;
    }

    /**
     * 提取政治面貌
     */
    private String extractPoliticalStatus(String text) {
        Pattern pattern = Pattern.compile("(?:政治面貌)[：:\\s]*([\\u4e00-\\u9fa5]{2,10})");
        Matcher matcher = pattern.matcher(text);

        if (matcher.find()) {
            String status = matcher.group(1);
            logger.debug("提取到政治面貌: {}", status);
            return status;
        }

        return null;
    }

    /**
     * 提取教育背景
     */
    private List<EducationInfo> extractEducationInfo(String text) {
        List<EducationInfo> educationList = new ArrayList<>();

        // 按行分割处理
        String[] lines = text.split("\\n");

        for (String line : lines) {
            // 查找包含时间和学校信息的行
            Pattern eduPattern = Pattern.compile("(\\d{4}\\.\\d{2}[-~](\\d{4}\\.\\d{2}|至今|现在))\\s*([\\u4e00-\\u9fa5]+大学|[\\u4e00-\\u9fa5]+学院)\\s*([\\u4e00-\\u9fa5()（）\\s]+)");
            Matcher matcher = eduPattern.matcher(line);

            if (matcher.find()) {
                EducationInfo info = new EducationInfo();
                info.setPeriod(matcher.group(1));
                info.setSchool(matcher.group(3));
                info.setMajorAndDegree(matcher.group(4));
                info.setRawText(line.trim());

                educationList.add(info);
                logger.debug("提取到教育信息: {} - {} - {}", info.getPeriod(), info.getSchool(), info.getMajorAndDegree());
            }
        }

        // 如果上面的模式没有匹配到，尝试更简单的模式
        if (educationList.isEmpty()) {
            Pattern simplePattern = Pattern.compile("(?:毕业院校)[：:\\s]*([\\u4e00-\\u9fa5]+大学)");
            Matcher matcher = simplePattern.matcher(text);
            if (matcher.find()) {
                EducationInfo info = new EducationInfo();
                info.setSchool(matcher.group(1));

                // 尝试找到学历信息
                Pattern degreePattern = Pattern.compile("(?:学\\s*历)[：:\\s]*([\\u4e00-\\u9fa5]+)");
                Matcher degreeMatcher = degreePattern.matcher(text);
                if (degreeMatcher.find()) {
                    info.setMajorAndDegree(degreeMatcher.group(1));
                }

                educationList.add(info);
                logger.debug("提取到基本教育信息: {} - {}", info.getSchool(), info.getMajorAndDegree());
            }
        }

        return educationList;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf('.');
        return lastDotIndex > 0 ? fileName.substring(lastDotIndex + 1) : "";
    }

    // 数据类定义
    @Data
    public static class ResumeInfo {
        private String source;
        private String originalText;
        private PersonalInfo personalInfo;
        private List<EducationInfo> educationInfo = new ArrayList<>();
    }

    @Data
    public static class PersonalInfo {
        private String name;
        private String phone;
        private String email;
        private String hometown;
        private String birthDate;
        private String politicalStatus;
        private Integer age;
    }

    @Data
    public static class EducationInfo {
        private String period;
        private String school;
        private String majorAndDegree;
        private String rawText;
    }
}
